package imooclambda;

import com.imooc.IMessageFormat;
import com.imooc.IUserCredential;
import com.imooc.impl.IMessageFormatImpl;
import com.imooc.impl.IUserCredentialImpl;

import java.util.UUID;
import java.util.function.*;

/**
 * @author steve
 * @date 2020/6/8 14:40
 */
public class App {
    public static void main(String[] args) {
        //1. 接口的静态方法和默认方法
        //默认方法
        IUserCredential ic = new IUserCredentialImpl();
        System.out.println(ic.verifyUser("admin"));
        System.out.println(ic.getCredential("admin"));
        //静态方法
        String msg = "hello world";
        if (IMessageFormat.verifyMessage(msg)) {
            IMessageFormat im = new IMessageFormatImpl();
            String format = im.format(msg, "json");
        }

        //匿名内部类，实现接口的抽象方法
        IUserCredential ic2 = new IUserCredential() {
            @Override
            public String verifyUser(String username) {
                return "admin".equals(username) ? "管理员" : "会员";
            }
        };
        System.out.println(ic2.verifyUser("admin"));
        System.out.println(ic2.verifyUser("manager"));

        //lambda表达式，实现接口的抽象方法
        IUserCredential ic3 = (String username) -> {
            return "admin".equals(username) ? "lambda管理员" : "lambda会员";
        };
        System.out.println(ic3.verifyUser("admin"));
        System.out.println(ic3.verifyUser("manager"));

        //3. jdk8提供的常见函数式接口
        /*
        java.util.function提供了大量的函数式接口
            Predicate:接收参数T对象，返回一个Boolean类型结果
            Consumer:接收参数T对象，没有返回值
            Function：接收参数T对象，返回R对象
            Supplier：不接收任何对象，只通过get()获取指定类型的对象
            UnaryOperator：接收参数对象T，执行完业务后，返回更新后的T对象
            BinaryOperator: 接收两个参数T对象，执行业务处理后，返回一个T对象
         */

        //传递一个用户名，返回用户名的验证成功与否的结构
        Predicate<String> pre = (String username) -> {
            return "admin".equals(username);
        };
        System.out.println(pre.test("manager"));
        System.out.println(pre.test("admin"));

        //消息发送(实际业务中，对某一业务进行功能性处理，并不需要返回值)
        Consumer<String> con = (String message) -> {
            System.out.println("要发送的消息" + message);
            System.out.println("消息发送完成");
        };
        con.accept("hello lambda");
        con.accept("hello yeah");

        //业务场景：前端传递一个字符串数据，而数据库中使用的是boolean类型的字段
        Function<String, Integer> fun = (String gender) -> {
            return "male".equals(gender) ? 0 : 1;
        };
        System.out.println(fun.apply("male"));
        System.out.println(fun.apply("female"));

        //不接受任何参数，提供T对象的创建工厂
        //创建自动生成系统密钥的工厂类型方法
        Supplier supplier = () -> {
            return UUID.randomUUID().toString();
        };
        System.out.println(supplier.get());
        System.out.println(supplier.get());
        System.out.println(supplier.get());

        //业务场景：用户通过前端传递一张图片，需要一个方法对图片的长宽尺寸进行处理，然后返回具体的结果(字符串例子)
        UnaryOperator<String> un = (String img) -> {
            img += "[100*200]";
            return img;
        };
        System.out.println(un.apply("原图--->"));

        //业务场景：在系统中的用户，可以和指定的任何一个用户进行pk，通过综合参数，决定他们的胜负，最后返回胜出的用户
        BinaryOperator<Integer> bo = (Integer i1, Integer i2) -> {
            return i1 > i2 ? i1: i2;
        };
        System.out.println(bo.apply(12, 15));


        // 1. lambda表达式的基本语法
        /*
        1)声明：就是和lambda表达式绑定的接口类型
        2)参数：包含在一对圆括号中，和绑定的接口中的抽象方法中的参数个数及顺序一致。
        3)操作符：->
        4)执行代码块：包含在一对大括号中，出现在操作符号的右侧

        [接口声明] = (参数) -> {执行代码块};
         */
//        ILambda1 i1 = () -> {
//            System.out.println("hello imooc!");
//            System.out.println("welcome to imooc!");
//        };
//        i1.test();
//
//        ILambda1 i2 = () -> System.out.println("hello imooc");
//        i2.test();
//
//        ILambda2 i21 = (String n, int a) -> {
//            System.out.println(n + "say: my year's old is " + a);
//        };
//        i21.test("jerry", 18);
//
//        ILambda2 i22 = (n, a) -> {
//            System.out.println(n + " 说：我今年" + a + "岁了.");
//        };
//        i22.test("tom", 22);
//
//        ILambda3 i3 = (x, y) -> {
//            int z = x + y;
//            return z;
//        };
//        System.out.println(i3.test(11, 22));
//
//        ILambda3 i31 = (x, y) -> x + y;
//        System.out.println(i31.test(100, 200));

        /*
        1. lambda表达式，必须和接口进行绑定。
        2. lambda表达式的参数，可以附带0个到n个参数，括号中的参数类型可以不用指定，jvm在运行时，会自动根据绑定的抽象方法中电参数进行推导。
        3. lambda表达式的返回值，如果代码块只有一行，并且没有大括号，不用写return关键字，单行代码的执行结果，会自动返回。
            如果添加了大括号，或者有多行代码，必须通过return关键字返回执行结果。
         */

    }

    // 没有参数，没有返回值的lambda表达式绑定的接口
    interface ILambda1{
        void test();
    }

    // 带有参数，没有返回值的lambda表达式
    interface ILambda2{
        void test(String name, int age);
    }

    // 带有参数，带有返回值的lambda表达式
    interface ILambda3 {
        int test(int x, int y);
    }
}
